#include "ctrlProccess.hpp"

#define PROCCESS_NUM 5
Task t;

struct EndPoint
{
public:
    pid_t _pid;
    int _fd;

public:
    EndPoint(pid_t pid, int fd) : _pid(pid), _fd(fd){};
    ~EndPoint(){};
};

void WaitTask();

void CreateProccess(std::vector<EndPoint> &ep)
{
    std::vector<int> fds;
    for (int i = 0; i < PROCCESS_NUM; i++)
    {
        // 创建管道
        int pipefd[2];
        int ret = pipe(pipefd);
        if (ret == -1)
        {
            std::cout << errno << " : " << strerror(errno) << std::endl;
            exit(1);
        }
        // 创建子进程
        pid_t id = fork();
        assert(id >= 0);
        if (id == 0)
        {
            for (auto &e : fds)
                close(e);
            // 子进程
            //  关闭多余文件描述符
            close(pipefd[1]);

            //重定向到从标准输入中读取
            dup2(pipefd[0], 0);
            // 处理
            //WaitTask(pipefd[0]);
            WaitTask();

            // 关闭剩下文件描述符
            close(pipefd[0]);
            exit(0);
        }
        // 父进程
        //  关闭多余文件描述符
        close(pipefd[0]);
        ep.push_back({id, pipefd[1]});
        fds.push_back(pipefd[1]);
    }
}

void WaitTask()
{
    while (1)
    {
        int taskid;
        ssize_t ret = read(0, &taskid, sizeof(taskid));
        if (ret == sizeof(int))
        {
            t.Excute(taskid);
        }
        else if (ret == 0)
        {
            std::cout << "exit........" << std::endl;
            break;
        }
        else
        {
            std::cout << "error" << std::endl;
            break;
        }
    }
    // int taskid;
    // ssize_t ret = read(fd, &taskid, sizeof(taskid));
    // if (ret == sizeof(int))
    // {
    //     t.Excute(taskid);
    // }
}

int Enum()
{
    int ret;
    std::cout << "---------------------------------" << std::endl;
    std::cout << "---0.数据库任务------1.打印任务---" << std::endl;
    std::cout << "---2.计算任务--------3.退出------" << std::endl;
    std::cout << "---------------------------------" << std::endl;
    std::cout << "---------------------------------" << std::endl;
    std::cout << "请输入你的选择 # " << std::endl;
    std::cin >> ret;
    return ret;
}

void WaitProccess(std::vector<EndPoint> &ep)
{
    // 关闭父进程写端
    // wait子进程
    for (int i = ep.size() - 1; i >= 0; i--)
    {
        close(ep[i]._fd);
        waitpid(ep[i]._pid, nullptr, 0);
    }

    // //关闭父进程写端
    // for(int i = 0; i < ep.size(); i++)
    //     close(ep[i]._fd);

    // //wait子进程
    // for(int i = 0; i < ep.size(); i++)
    //     waitpid(ep[i]._pid, nullptr, 0);
}

int main()
{
    std::vector<EndPoint> ep; // 进程池
    Task task;                // 任务列表
    // 创建一批进程
    CreateProccess(ep);

    while (1)
    {
        // 选取任务
        int ret = Enum();
        if (ret == 3)
            break;
        if (ret < 0 || ret > 3)
            continue;
        // int taskid = rand() % task.funcs.size();
        //  选择进程
        int pid = rand() % PROCCESS_NUM;
        // 发送给相应的进程执行
        write(ep[pid]._fd, &ret, sizeof(ret));
        sleep(1);
        // for(int i = 0; i < 5; i++)
        // {
        //     write(ep[i]._fd, &i, sizeof(i));
        //     sleep(1);
        // }
    }
    WaitProccess(ep);

    return 0;
}
